package com.youhong.teethcare.utils;

import android.util.Log;

import com.google.gson.Gson;

import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Cookie;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

public class HttpJsonUtils2 {

    /**
     * http://47.92.125.146:8082/babies/{BabyId}/avatar
     **/


    //public static final String URL_FEEDBACK = ROOT_URL +"/opinion/save";

    public static final String URL_OTA = "http://api.le-young.com/device/firmware/update";
    public static final String URL_FEEDBACK= "http://api.le-young.com/intlsso/opinion/save";

    static String json_str = "";
    static boolean isNetworkThreadFinished = true;

    /**
     * Constnats
     **/
    public final static int CODE_SUCCESS = 0;
    public final static int CODE_ERROR = 310;
    public final static int CODE_FAIL = 0x9;
    public final static int CODE_INVALID_FORMAT = 301;
    public final static int CODE_ERR_VALIDATING_CODE = 4;



    public synchronized static <T> T doPostFormEncoded_Sync(final String url, final List<NameValuePair> params,
                                                            Class<T> cls) {

        isNetworkThreadFinished = false;
        json_str = "";

        new Thread() {
            @Override
            public void run() {

                OkHttpClient client = new OkHttpClient();
                MediaType mediaType = MediaType.parse("multipart/form-data; boundary=---011000010111000001101001");
                MultipartBody.Builder bodyBuilder = new MultipartBody.Builder();
                bodyBuilder.setType(mediaType);
                if (params != null) {
                    for (NameValuePair pair : params) {

                        if (pair instanceof FileNameValuePair) {

                            FileNameValuePair file_pair = (FileNameValuePair) pair;
                            bodyBuilder.addFormDataPart(pair.getName(), pair.getValue(), RequestBody.create

                                    (MediaType.parse(file_pair.getMediaType()), file_pair.getFile()));

                        } else {

                            bodyBuilder.addFormDataPart(pair.getName(), pair.getValue());
                        }
                    }
                }
                try {

                    RequestBody body = bodyBuilder.setType(MultipartBody.FORM).build();

                    Request request = new Request.Builder().url(url).post(body)
                            .addHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001")
                            .addHeader("cache-control", "no-cache").build();

                    Buffer buffer = new Buffer();

                    request.body().writeTo(buffer);

                    Log.w("Request.Body", buffer.readUtf8());
                    Response response = client.newCall(request).execute();

                    if (response.isSuccessful()) {

                        json_str = response.body().string();

                    } else {

                        throw new IOException("Unexpected code " + response);

                    }

                    Log.w("Response.Body", json_str);

                    isNetworkThreadFinished = true;

                } catch (ClientProtocolException e) {

                    // Log.e("Error:", e.getMessage());
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (IOException e) {
                    // Log.e("Error:", e.getMessage());
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (Exception e) {
                    // Log.e("Error:", e.getMessage() + "abc");
                    e.printStackTrace();
                    isNetworkThreadFinished = true;
                }

            }

        }.start();

        while (!isNetworkThreadFinished) {

            try {
                Thread.currentThread().sleep(50);
            } catch (InterruptedException e) { // TODO Auto-generated catch
                // block e.printStackTrace(); }

            }
        }

        Gson gson = new Gson();
        T t = gson.fromJson(json_str, cls);
        return t;
    }

    public synchronized static <T> T doGetHttpRequest_Sync(final String url, final List<NameValuePair> params,
                                                           Class<T> cls) {

        isNetworkThreadFinished = false;
        json_str = "";

        new Thread() {
            @Override
            public void run() {

                OkHttpClient client = new OkHttpClient();

                String param_str = "";
                if (params != null) {
                    StringBuffer param_buffer = new StringBuffer();
                    param_buffer.append('?');
                    for (int i = 0; i < params.size(); i++) {

                        if (i != 0) {
                            param_buffer.append('&');
                        }

                        param_buffer.append(params.get(i).getName());
                        param_buffer.append('=');
                        param_buffer.append(params.get(i).getValue());
                    }
                    param_str = param_buffer.toString();

                }

                try {

                    Request request = new Request.Builder().url(url + param_str).build();

                    Log.e("Request.Url:", url + param_str);
                    Response response = client.newCall(request).execute();

                    if (response.isSuccessful()) {

                        json_str = response.body().string();

                    } else {

                        throw new IOException("Unexpected code " + response);

                    }

                    Log.w("Response.Body", json_str);
                    isNetworkThreadFinished = true;

                } catch (ClientProtocolException e) {

                    Log.e("Error:", e.getMessage());
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (IOException e) {
                    Log.e("Error:", e.getMessage() + "a");
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (Exception e) {
                    Log.e("Error:", e.getMessage() + "abc");
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                }

            }

        }.start();

        while (!isNetworkThreadFinished) {

            try {
                Thread.currentThread().sleep(50);
            } catch (InterruptedException e) { // TODO Auto-generated catch
                // block e.printStackTrace(); }

            }
        }
        Gson gson = new Gson();
        T t = gson.fromJson(json_str, cls);
        return t;

    }

    public synchronized static <T> T doDeleteHttpRequest_Sync(final String url, final List<NameValuePair> params,
                                                              Class<T> cls) {

        isNetworkThreadFinished = false;
        json_str = "";

        new Thread() {
            @Override
            public void run() {

                OkHttpClient client = new OkHttpClient();

                String param_str = "";
                if (params != null) {
                    StringBuffer param_buffer = new StringBuffer();
                    param_buffer.append('?');
                    for (int i = 0; i < params.size(); i++) {

                        if (i != 0) {
                            param_buffer.append('&');
                        }

                        param_buffer.append(params.get(i).getName());
                        param_buffer.append('=');
                        param_buffer.append(params.get(i).getValue());
                    }
                    param_str = param_buffer.toString();

                }

                try {

                    Request request = new Request.Builder().url(url + param_str).delete().build();

                    Log.e("Request.Url:", url + param_str);
                    Response response = client.newCall(request).execute();

                    if (response.isSuccessful()) {

                        json_str = response.body().string();

                    } else {

                        throw new IOException("Unexpected code " + response);

                    }

                    Log.w("Response.Body", json_str);
                    isNetworkThreadFinished = true;

                } catch (ClientProtocolException e) {

                    Log.e("Error:", e.getMessage());
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (IOException e) {
                    Log.e("Error:", e.getMessage() + "a");
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (Exception e) {
                    Log.e("Error:", e.getMessage() + "abc");
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                }

            }

        }.start();

        while (!isNetworkThreadFinished) {

            try {
                Thread.currentThread().sleep(50);
            } catch (InterruptedException e) { // TODO Auto-generated catch
                // block e.printStackTrace(); }

            }
        }
        Gson gson = new Gson();
        T t = gson.fromJson(json_str, cls);
        return t;

    }

    public static <T> T doPostFormMultipart_Async(final String url, final List<NameValuePair> params, Class<T> cls) {

        json_str = "";
        String entry_string = "-----011000010111000001101001" + "\r\n" + "User-Disposition: form-data; name=\"%s\""
                + "\r\n" + "\r\n" + "%s" + "\r\n";


        OkHttpClient client = new OkHttpClient();

        MediaType mediaType = MediaType.parse("multipart/form-data; boundary=---011000010111000001101001");

        String bodyString = "";

        for (NameValuePair pair : params) {

            bodyString += String.format(entry_string, pair.getName(), pair.getValue());

        }
        bodyString += "-----011000010111000001101001--";

        RequestBody body = RequestBody.create(mediaType, bodyString);
        Buffer buffer = new Buffer();
        try {
            body.writeTo(buffer);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        Log.w("Request.body", buffer.readUtf8());

        Request request = new Request.Builder().url(url).post(body)
                .addHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001")
                .addHeader("cache-control", "no-cache").build();
        Response response = null;
        try {
            response = client.newCall(request).execute();

            if (response.isSuccessful()) {

                try {
                    json_str = response.body().string();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            for (int i = 0; i < response.headers().size(); i++) {

                Log.w("HeaderName=" + response.headers().name(i) + ":", "" + response.headers().value(i));
            }

            Log.w("Response.body", json_str);

        } catch (IOException e) {

            e.printStackTrace();

        }
        Gson gson = new Gson();
        return gson.fromJson(json_str, cls);
    }


    public static <T> T doPostUrlEncoded(final String url, final List<NameValuePair> params, Class<T> cls) {
        isNetworkThreadFinished = false;
        json_str = "";

        new Thread() {
            public void run() {
                // HttpResponse mResponse = null;
                // HttpClient client = new DefaultHttpClient();
                OkHttpClient client = new OkHttpClient();

                boolean isFirstParam = true;

                String bodyString = "";

                if (params != null) {
                    for (NameValuePair pair : params) {

                        if (isFirstParam) {

                            isFirstParam = !isFirstParam;

                            bodyString += pair.getName() + "=" + pair.getValue();

                        } else {

                            bodyString += "&" + pair.getName() + "=" + pair.getValue();

                        }

                    }
                }

                try {

                    RequestBody body = RequestBody.create(null, bodyString);

                    Request request = new Request.Builder().url(url).post(body)
                            .addHeader("content-type", "application/x-www-form-urlencoded").build();

                    Buffer buffer = new Buffer();

                    request.body().writeTo(buffer);

                    Log.w("Request.Body", buffer.readUtf8());

                    Response response = client.newCall(request).execute();

                    if (response.isSuccessful()) {

                        json_str = response.body().string();

                    } else {

                        throw new IOException("Unexpected code " + response);

                    }

                    Log.w("Response.Body", json_str);

                } catch (ClientProtocolException e) {

                    Log.e("Error:", e.getMessage());
                    e.printStackTrace();
                    isNetworkThreadFinished = true;
                } catch (IOException e) {
                    Log.e("Error:", e.getMessage());
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                } catch (Exception e) {
                    Log.e("Error:", e.getMessage() + "abc");
                    e.printStackTrace();
                    isNetworkThreadFinished = true;

                }

                isNetworkThreadFinished = true;
            }
        }.start();

        while (!isNetworkThreadFinished)

        {

            try {
                Thread.currentThread().sleep(50);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

        Gson gson = new Gson();
        T t = gson.fromJson(json_str, cls);
        return t;

    }

    public static <T> T doPostFormUrlEncodedConsistedCookie(final String url, final List<NameValuePair> params,
                                                            Class<T> cls, String[] cookie) {

        Log.e("Url:", url);

        OkHttpClient client = new OkHttpClient();
        boolean isFirstParam = true;
        String bodyString = "";
        if (params != null) {
            for (NameValuePair pair : params) {

                if (isFirstParam) {

                    isFirstParam = !isFirstParam;

                    bodyString += pair.getName() + "=" + pair.getValue();
                } else {

                    bodyString += "&" + pair.getName() + "=" + pair.getValue();
                }

            }
        }

        try {

            RequestBody body = RequestBody.create(null, bodyString);

            Request.Builder request_builder = new Request.Builder().url(url).post(body)
                    .addHeader("content-type", "application/x-www-form-urlencoded");

            if (cookie[0] != null && !cookie[0].equals("")) {
                Log.w("Cookie", cookie[0]);
                request_builder.header("Cookie", cookie[0]);
            }

            Request request = request_builder.build();

            Buffer buffer = new Buffer();

            request.body().writeTo(buffer);

            Log.w("Request.Body", buffer.readUtf8());

            // Execution
            Response response = client.newCall(request).execute();

            List<Cookie> cookies = Cookie.parseAll(request.url(), response.headers());

            cookie[0] = cookieHeader(cookies);

            if (response.isSuccessful()) {

                json_str = response.body().string();

            } else {

                throw new IOException("Unexpected code " + response);

            }

            Log.w("Response.Body", json_str);

        } catch (ClientProtocolException e) {

            Log.e("Error:", e.getMessage());
            e.printStackTrace();
            isNetworkThreadFinished = true;

        } catch (IOException e) {
            Log.e("Error:", e.getMessage());
            e.printStackTrace();
            isNetworkThreadFinished = true;

        } catch (Exception e) {
            Log.e("Error:", e.getMessage() + "abc");
            e.printStackTrace();
            isNetworkThreadFinished = true;

        }

        Gson gson = new Gson();
        T t = gson.fromJson(json_str, cls);
        return t;
    }

    public static <T> T doPostFormMultipartConsistedCookie(final String url, final List<NameValuePair> params,
                                                           Class<T> cls, String cookie) {

        json_str = "";

        OkHttpClient client = new OkHttpClient();

        // MediaType mediaType = new MediaT

        MultipartBody.Builder multipartbody_builder = new MultipartBody.Builder();

        MultipartBody body = multipartbody_builder.build();
        for (NameValuePair pair : params) {
            multipartbody_builder.addFormDataPart(pair.getName(), pair.getValue());
        }

        Request.Builder request_builder = new Request.Builder();

        request_builder.post(body);

        Buffer buffer = new Buffer();
        try {
            body.writeTo(buffer);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        Log.w("Request.body", buffer.readUtf8());

        Request request = new Request.Builder().url(url).post(body).addHeader("cache-control", "no-cache").build();

        Response response = null;
        try {
            response = client.newCall(request).execute();

            if (response.isSuccessful()) {

                try {
                    json_str = response.body().string();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            Log.w("Response.body", json_str);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Gson gson = new Gson();
        return gson.fromJson(json_str, cls);

    }

    private static String cookieHeader(List<Cookie> cookies) {
        StringBuilder cookieHeader = new StringBuilder();
        for (int i = 0, size = cookies.size(); i < size; i++) {
            if (i > 0) {
                cookieHeader.append("; ");
            }
            Cookie cookie = cookies.get(i);
            cookieHeader.append(cookie.name()).append('=').append(cookie.value());
        }
        return cookieHeader.toString();
    }

    private static boolean result = false;

    public interface downloadCallback {

        public void downloadOver(boolean isSucess, long fileSize);

    }

    public static void downloadFile(final String targetPath, final String localPath, final downloadCallback callback) {

        OkHttpClient client = new OkHttpClient();
        Request.Builder request_builder = new Request.Builder();

        // File path
        request_builder.url(targetPath);
        Request request = request_builder.build();

        OkHttpClient mOkHttpClient = new OkHttpClient();
        mOkHttpClient.newCall(request).enqueue(new Callback() {

            @Override
            public void onResponse(Call call, Response resp) throws IOException {

                InputStream is = null;
                RandomAccessFile random_af = null;
                byte[] buffer = new byte[2048];
                long size = resp.body().contentLength();
                try {

                    is = resp.body().byteStream();
                    random_af = new RandomAccessFile(new File(localPath), "rw");

                    int byteOffset = 0;
                    int read_count = 0;
                    while ((read_count = is.read(buffer)) != -1) {

                        byteOffset += read_count;
                        random_af.write(buffer, 0, read_count);
                    }
                    result = true;

                    is.close();
                    random_af.close();
                    callback.downloadOver(result, size);
                } catch (Exception e) {

                    result = false;
                    if (is != null) {
                        is.close();
                    }
                    if (random_af != null) {
                        random_af.close();
                    }
                    e.printStackTrace();
                    callback.downloadOver(result, size);
                }
            }

            @Override
            public void onFailure(Call call, IOException ex) {

                callback.downloadOver(false, 0);
            }
        });

    }

    public static class FileNameValuePair implements NameValuePair {

        private String name;
        private String value;
        private File file;
        private String mediaType;

        public FileNameValuePair(String name, String fileName, File file, String mediaType) {

            this.name = name;
            this.value = fileName;
            this.file = file;
            this.mediaType = mediaType;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getValue() {
            return value;
        }

        public File getFile() {

            return file;
        }

        public String getMediaType() {

            return mediaType;

        }

    }
}
